package com.hyj.serve.manage.configure.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;

import java.io.Serializable;
import java.sql.Timestamp;

/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author Wuyongsheng
 * @create 2019 /7/17
 * @since 1.0.0
 */
@Slf4j
@Data
public class Result<T> implements Serializable {

    private static final long serialVersionUID = -5399051578054163779L;
    private int code;
    private String message;
    private T data;
    private String path;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",  timezone="GMT+8")
    private Timestamp currentTime = new Timestamp(System.currentTimeMillis());


    public Result<T> setCode(Code resultCode) {
        this.code = resultCode.value();
        return this;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public Result<T> setMessage(String message) {
        this.message = message;
        return this;
    }

    public Object getData() {
        return data;
    }

    public Result<T> setData(T data) {
        this.data = data ;
        return this;
    }

    public Timestamp getCurrentTime() {
        return currentTime;
    }

    public Result<T> setCurrentTime(Timestamp currentTime) {
        this.currentTime = currentTime;
        return this;
    }

    public Result<T> setCode(int code) {
        this.code = code;
        return this;
    }

    public Result<T> setPath(String path) {
        this.path = path;
        return this;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this, SerializerFeature.WriteDateUseDateFormat);
    }

    public static <T> Result.Builder<T> ok(){
        return new Builder<T>()
                .message("ok")
                .code(Code.OK.value);
    }
    public static <T> Result.Builder<T> ok(T t){
        return new Builder<T>()
                .message("ok")
                .code(Code.OK.value)
                .data(t);
    }
    public static <T> Result.Builder<T> ok(T t,String message){
        return new Builder<T>()
                .message(message)
                .code(Code.OK.value)
                .data(t);
    }
    public static <T> Result.Builder<T> ok(T t,  String format, Object... args){
        return new Builder<T>()
                .message(String.format(format,args))
                .code(Code.OK.value)
                .data(t);
    }

    public static <T> Result.Builder<T> fail(String message){
        return new Builder<T>()
                .message(message)
                .code(Code.FAILURE.value);
    }
    public static <T> Result.Builder<T> fail( String format, Object... args){
        return new Builder<T>()
                .message(String.format(format,args))
                .code(Code.FAILURE.value);
    }

    /**
     * 编码类型
     */
    public enum Code {
        /**
         * 成功
         */
        OK(200),
        BAD_REQUEST(400),
        UNAUTHORIZED(401),
        FORBIDDEN(403),
        NOT_FOUND(404),
        METHOD_NOT_ALLOWED(405),
        INTERNAL_SERVER_ERROR(500),
        NOT_IMPLEMENTED(501),
        BAD_GATEWAY(502),
        SERVICE_UNAVAILABLE(503),
        GATEWAY_TIMEOUT(504),
        FAILURE(600);

        private final int value;

        Code(int value) {
            this.value = value;
        }

        public int value() {
            return value;
        }
    }

    /**
     * A builder for {@link Result}.
     * @param <T>
     */
    public static class Builder<T> implements Serializable{

        private static final long serialVersionUID = 3204431115256023021L;

        private int code;
        private String message;
        private T data;
        private String path;
        private Timestamp currentTime;


        public Result<T> build() {
            Result<T> result  = new Result<>();
            result.code = this.code;
            result.message = this.message;
            result.path = this.path;
            result.currentTime = this.currentTime == null ? new Timestamp(System.currentTimeMillis()) : this.currentTime;
            result.data = data;
            return result;
        }

        public Builder<T> code(int code){
            this.code = code;
            return this;
        }

        public Builder<T> code(HttpStatus httpStatus){
            this.code = httpStatus.value();
            return this;
        }
        public Builder<T> code(Result.Code code){
            this.code = code.value();
            return this;
        }
        public Builder<T> message(String message){
            this.message = message;
            return this;
        }
        public Builder<T> message(String format, Object... args){
            this.message = String.format(format,args);
            return this;
        }
        public Builder<T> path(String path){
            this.path = path;
            return this;
        }

        public Builder<T> data(T data){
            this.data = data;
            return this;
        }

        public Builder<T> currentTime(Timestamp currentTime){
            this.currentTime = currentTime;
            return this;
        }


    }

}